package com.yuandian.bpm.common.data.datascope;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import lombok.Setter;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.List;
import java.util.Map;

/**
 * 说明：bpm数据权限处理拦截器
 * @Author zfsn
 * @Date 2023/2/14 10:20
 */
public class BpmScopeInterceptor implements DataScopeInterceptor {

	@Setter
	private DataScopeHandle dataScopeHandle;

	@Override
	public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
							ResultHandler resultHandler, BoundSql boundSql) {
		PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);

		String originalSql = boundSql.getSql();
		Object parameterObject = boundSql.getParameterObject();

		// 查找参数中包含BpmScope类型的参数
		BpmScope bpmScope = findBpmScopeObject(parameterObject);
		if (bpmScope == null) {
			return;
		}

		String systemIdFieldName = bpmScope.getSystemIdFieldName();
		Map<String, List<?>> permissionMap = bpmScope.getPermissionMap();
		// 优先获取赋值数据
		if (CollUtil.isEmpty(permissionMap) && dataScopeHandle.calcScope(bpmScope)) {
			originalSql = String.format("SELECT %s FROM (%s) temp_bpm_scope",
					bpmScope.getFunc().getType(), originalSql);
			mpBs.sql(originalSql);
			return;
		}

		// 用于粗略判断需要校验权限的字段是否在sql中存在，如果不存在就忽略该权限校验
		String fromSql = originalSql.substring(0, originalSql.indexOf("FROM"));

		StringBuilder sb = new StringBuilder();
		permissionMap.forEach((fieldName, list) -> {
			if (CollUtil.isNotEmpty(list) && fromSql.contains(fieldName)) {
				String join;
				if (fieldName.equals(systemIdFieldName)) {
					join = CollectionUtil.join(list, ",");
				} else {
					join = CollectionUtil.join(list, ",", "'", "'");
				}
				sb.append("AND temp_bpm_scope.`")
						.append(fieldName)
						.append("` IN (")
						.append(join)
						.append(") ");
			}
		});

		originalSql = String.format("SELECT %s FROM (%s) temp_bpm_scope WHERE 1 = 1 %s",
				bpmScope.getFunc().getType(), originalSql, sb);

		mpBs.sql(originalSql);
	}

	/**
	 * 查找参数是否包括BpmScope对象
	 * @param parameterObj 参数列表
	 * @return BpmScope
	 */
	private BpmScope findBpmScopeObject(Object parameterObj) {
		if (parameterObj instanceof BpmScope) {
			return (BpmScope) parameterObj;
		}
		else if (parameterObj instanceof Map) {
			for (Object val : ((Map<?, ?>) parameterObj).values()) {
				if (val instanceof BpmScope) {
					return (BpmScope) val;
				}
			}
		}
		return null;
	}
}
